#ifndef _XLCD_SD
#define _XLCD_SD

#define NO_SD
#include "SPIFFS.h"
#include <FS.h>
#if not defined(NO_SD)
#include "SD.h"
#endif
#include <ArduinoJson.h>
#include <Arduino.h>
#include "../logger.h"
#define XTOUCH_FS SPIFFS
bool xtouch_filesystem_exist(fs::FS &fs, const char *path)
{
    return fs.exists(path);
}

fs::File xtouch_filesystem_open(fs::FS &fs, const char *path)
{
    return fs.open(path);
}

bool xtouch_filesystem_deleteFile(fs::FS &fs, const char *path)
{
    return fs.remove(path);
}

#if not defined(NO_SD)
bool xtouch_filesystem_mkdir(fs::FS &fs, const char *path)
{
    if (!xtouch_filesystem_exist(SD, path))
    {
        return fs.mkdir(path);
    }
    return true;
}
bool xtouch_filesystem_rmdir(fs::FS &fs, const char *path)
{
    return fs.rmdir(path);
}
#else
bool xtouch_filesystem_mkdir(fs::FS &fs, const char *path)
{
    logf("spiffs not support make dir :\"%s\"", path);
    return true;
}
bool xtouch_filesystem_rmdir(fs::FS &fs, const char *path)
{
    logf("spiffs not support remove dir :\"%s\"", path);
    return true;
}
#endif

void xtouch_filesystem_writeJson(fs::FS &fs, const char *filename, DynamicJsonDocument json, bool defaultsToArray = false, int size = 1024)
{
    logf("Writting JSON file: %s\n", filename);
    fs::File configFile = fs.open(filename, FILE_WRITE);
    if (!configFile)
    {
        logf("[SD] Failed to write json file: %s", filename);
        return;
    }

    serializeJson(json, configFile);
    configFile.close();
}

DynamicJsonDocument xtouch_filesystem_readJson(fs::FS &fs, const char *filename, bool defaultsToArray = false, int size = 1024)
{
    logf("[SD] Reading JSON file: %s", filename);
    DynamicJsonDocument doc(size); // Adjust the size as needed

    if (!fs.exists(filename))
    {
        logf("[SD] Error Reading JSON File: %s", filename);
        if (defaultsToArray)
        {
            return doc.createNestedArray();
        }
        else
        {
            return doc;
        }
    }

    fs::File configFile = fs.open(filename);
    DeserializationError error = deserializeJson(doc, configFile);

    if (error)
    {
        logf("[SD] Error Parsing JSON File: %s", filename);
    }

    configFile.close();
    return doc;
}

void file_dump_to_log(fs::FS &fs, const char *filename){
    logln("[SD] Dumping File Contents:");
    fs::File file = fs.open(filename, FILE_READ);
    if (!file) {
        logf("[SD] Failed to open file: %s", filename);
        return;
    }
    logf("[SD] File: %s, Size: %d bytes", filename, file.size());
    while (file.available()) {   
        ConsoleInfo.write(file.read());
    }
}

void fs_dealer(String cmd) {
    String path;
    if (cmd.startsWith("ls")) {
        path = cmd.substring(2);
        path.trim();
        if (path.length() == 0) {
            path = "/";
        }
        fs::File root = SPIFFS.open(path);
        if (!root) {
            logf("[FS] Failed to open directory: %s", path.c_str());
            return;
        }
        logf("[FS] Listing files in: %s", path.c_str());
        fs::File file = root.openNextFile();
        while (file) {
            logf("[FS] File: %s, Size: %d bytes", file.name(), file.size());
            file = root.openNextFile();
        }
    } else if(cmd.startsWith("cat ")) {
        path = cmd.substring(3);
        path.trim();
        logf("[FS] Dumping \"%s\"", path.c_str());
        file_dump_to_log(XTOUCH_FS, path.c_str());
    }else {
        logf("[CLI] Unknown filesystem command \"%s\"", cmd.c_str());
    }
}

void filesystem_init() {
    if (!SPIFFS.begin(true)) {
        logln("[FS] SPIFFS Mount Failed");
        return;
    } else {
        logln("[FS] SPIFFS Mount Successful");
    } 
}

#endif